//Rational.cpp
#include "Rational.h"
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
int gcd(int, int);

void Rational::standardization() {
    int g = gcd(abs(this->nume),abs(this->deno));
	this->deno = this->deno / g;
	this->nume = this->nume / g;

    if ((this->deno * this->nume) < 0) {
        this->nume = -abs(this->nume);
        this->deno = abs(this->deno);
    } else {
        this->nume = abs(this->nume);
        this->deno = abs(this->deno);
    }
}

Rational::Rational(int n, int d) {
    if (d == 0) {
        cout << "��ĸ����Ϊ0" << endl;
    } else {
        this->nume = n;
        this->deno = d;
    }
    standardization();
}

Rational::Rational(double num) {
    if (num == 0) {
        this->nume = 0;
        this->deno = 1;
        standardization();
    } else {
        int i = 1;
        for (;;i *= 10) {
            if ((num * i - (int)(num * i)) == 0) {
                break;
            }
        }
        this->nume = num * i;
        this->deno = i;
        standardization();
    }
}

Rational::Rational(const Rational &rational) {
    this->nume = rational.nume;
    this->deno = rational.deno;
    standardization();
}

void Rational::myPrint() {
    standardization();
    if (this->nume == 0) {
        cout << 0 << endl;
    } else if (this->deno == 1) {
        cout << this->nume << endl;
    } else {
        cout << this->nume << "/" << this->deno << endl;
    }
}

Rational operator+(const Rational& r1, const Rational& r2) {
    Rational r;
    r.nume = r1.nume * r2.deno + r2.nume * r1.deno;
    r.deno = r1.deno * r2.deno;
    return r;
}

Rational operator-(const Rational& r1, const Rational& r2) {
    Rational r;
    r.nume = r1.nume * r2.deno - r2.nume * r1.deno;
    r.deno = r1.deno * r2.deno;
    return r;
}

Rational operator*(const Rational& r1, const Rational& r2) {
    Rational r(r1.nume * r2.nume, r1.deno * r2.deno);
    return r;
}

Rational operator/(const Rational& r1, const Rational& r2) {
    Rational r(r1.nume * r2.deno, r2.nume * r1.deno);
    return r;
}

Rational& Rational::operator=(const Rational& r) {
    if (this != &r) {
        this->nume = r.nume;
        this->deno = r.deno;
    }
	return *this;
}

Rational& Rational::operator+=(const Rational &r) {
    this->nume = this->nume * r.deno + r.nume * this->deno;
    this->deno = this->deno * r.deno;
    standardization();
    return *this;
}

Rational& Rational::operator-=(const Rational &r) {
    this->nume = this->nume * r.deno - r.nume * this->deno;
    this->deno = this->deno * r.deno;
    standardization();
    return *this;
}

Rational& Rational::operator*=(const Rational &r) {
    this->nume = this->nume * r.nume;
    this->deno = this->deno * r.deno;
    standardization();
    return *this;
}

Rational& Rational::operator/=(const Rational &r) {
    this->nume = this->nume * r.deno;
    this->deno = r.nume * this->deno;
    standardization();
    return *this;
}

bool operator<(const Rational& r1, const Rational& r2) {
     if (((r1.nume * r2.deno - r2.nume * r1.deno) * r1.deno * r2.nume) < 0) {
        return true;
    }
    return false;
}

bool operator>(const Rational& r1, const Rational& r2) {
    if (((r1.nume * r2.deno - r2.nume * r1.deno) * r1.deno * r2.nume) > 0) {
        return true;
    }
    return false;
}

bool operator==(const Rational& r1, const Rational& r2) {
    if ((r1.deno * r2.nume) == (r1.nume * r2.deno)) {
        return true;
    }
    return false;
}

Rational& Rational::operator++() {
    this->nume = this->nume + this->deno;
    standardization();
    return *this;
}

Rational Rational::operator++(int) {
    Rational r(*this);
    this->nume = this->nume + this->deno;
    standardization();
    return r;
}

Rational& Rational::operator--() {
    this->nume = this->nume - this->deno;
    standardization();
    return *this;
}

Rational Rational::operator--(int) {
    Rational r(*this);
    this->nume = this->nume - this->deno;
    standardization();
    return r;
}

ostream& operator<<(ostream& os, const Rational& r) {
    if (r.nume == 0) {
        os << 0;
    } else if (r.deno == 1) {
        os << r.nume;
    } else {
        os << r.nume << "/" << r.deno;
    }
    return os;
}

istream& operator>>(istream& in, Rational& r) {
    string str;
    in >> str;
    int pos = str.find("/");
    if (pos == -1) {
        r.nume = 0;
        for (int i = 0; i < str.size(); i++) {
            r.nume = r.nume * 10 + (int)(str.at(i) - '0');
        }
        in >> str;
        r.deno = 0;
        for (int i = 0; i < str.size(); i++) {
            r.deno = r.deno * 10 + (int)(str.at(i) - '0');
        }
    } else {
        r.nume = 0;
        r.deno = 0;
        for (int i = 0; i < pos; i++) {
            r.nume = r.nume * 10 + (int)(str.at(i) - '0');
        }
        for (int i = pos + 1; i < str.size(); i++) {
            r.deno = r.deno * 10 + (int)(str.at(i) - '0');
        }
    }
    r.standardization();
    return in;
}

int gcd(int a, int b) {
	if (a % b == 0) {
		return b;
	}
	return gcd(b,a % b);
}